////////////////////////////////////////////////////////////////////////////////
/// CTCInterrupt.c
/// Example File to blink all LEDS attached to PORTB at 50hz using TIMER1
/// and CTC attached to an Interrupt
/// Connections:
/// Leds connected to PORTB0-7 Active Low
/// Clock set at 1mHz
////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////
/// CTC.c
/// Example File to blink all LEDS attached to PORTB at 50hz using TIMER1
/// and the CTC feature.
/// Connections:
/// Leds connected to PORTB0-7 Active Low
/// Clock set at 1mHz
////////////////////////////////////////////////////////////////////////////////



/// NO PRESCALER 
////////////////////////////////////////
/// Timer Resolution = (1 / Input Frequency)
////////////////////////////////////////
/// NO PRESCALER
////////////////////////////////////////
/// Target Count = (1 / Target Frequency) / ( 1 / Timer Clock Frequency) - 1
/// = (1 / 20) / (1 / 1000000) - 1
/// = 49999
////////////////////////////////////////
/// PRESCALER ENABLED
////////////////////////////////////////
/// Timer Resolution = (Prescale / Input Frequency)
////////////////////////////////////////
///Prescaler Value | Resolution @ 1MHz 
///              1 |  1uS 
///              8 |  8uS 
///             64 | 64uS 
///            256 | 256uS 
///           1024 | 1024uS
////////////////////////////////////////
/// Target Timer Count = (Input Frequency / Prescale) / Target Frequency - 1
////////////////////////////////////////


////////////////////////////////////////
/// Hardware SPI Connections
///
/// /OE -> Ground
/// SER -> MOSI
/// SRCLK -> SCK
/// /SRCLR -> 5V
/// RCLK -> /SS
///
/// SER = Serial Data In
/// SRCLK = Shift Register Clock
////////////////////////////////////////

#define DATA_PIN 6
#define CLOCK_PIN 8
#define LATCH_PIN 5

#define DATA_PIN_PORTB (DATA_PIN - 1)
#define CLOCK_PIN_PORTB (CLOCK_PIN - 1)
#define LATCH_PIN_PORTB (LATCH_PIN - 1)



//Include the Header file for Input/Output Operations
#include <avr/io.h>
//Include the Header file for Interrupts
#include <avr/interrupt.h>
//Include library for Program Memory
#include <avr/pgmspace.h>

void softwareShiftOut(uint8_t data);

	///////////////
	// Variables //	
	///////////////
	uint8_t data[30];
	uint8_t index = 0;

	uint8_t characters[128][5] PROGMEM=
	{
		{0x00,0x00,0x00,0x00,0x00 }, //Blank 0
		{0x00,0x00,0x00,0x00,0x00 }, //Blank 1
		{0x00,0x00,0x00,0x00,0x00 }, //Blank 2
		{0x00,0x00,0x00,0x00,0x00 }, //Blank 3
		{0x00,0x00,0x00,0x00,0x00 }, //Blank 4
		{0x00,0x00,0x00,0x00,0x00 }, //Blank 5
		{0x00,0x00,0x00,0x00,0x00 }, //Blank 6
		{0x00,0x00,0x00,0x00,0x00 }, //Blank 7
		{0x00,0x00,0x00,0x00,0x00 }, //Blank 8
		{0x00,0x00,0x00,0x00,0x00 }, //Blank 9
		{0x00,0x00,0x00,0x00,0x00 }, //Blank 10
		{0x00,0x00,0x00,0x00,0x00 }, //Blank 11
		{0x00,0x00,0x00,0x00,0x00 }, //Blank 12
		{0x00,0x00,0x00,0x00,0x00 }, //Blank 13
		{0x00,0x00,0x00,0x00,0x00 }, //Blank 14
		{0x00,0x00,0x00,0x00,0x00 }, //Blank 15
		{0x00,0x00,0x00,0x00,0x00 }, //Blank 16
			
		{0x00,0x00,0x4F,0x00,0x00},	// !
		{0x00,0x07,0x00,0x07,0x00},	// "
		{0x14,0x7F,0x14,0x7F,0x14},	// #
		{0x24,0x2A,0x7F,0x2A,0x12},	// $
		{0x23,0x13,0x08,0x64,0x62},	// %
		{0x36,0x49,0x55,0x22,0x50},	// &
		{0x00,0x05,0x03,0x00,0x00},	// '
		{0x00,0x1C,0x22,0x41,0x00},	// (
		{0x00,0x41,0x22,0x1C,0x00},	// )
		{0x14,0x08,0x3E,0x08,0x14},	// *
		{0x08,0x08,0x3E,0x08,0x08},	// +
		{0x00,0x50,0x30,0x00,0x00},	// ,
		{0x08,0x08,0x08,0x08,0x08},	// -
		{0x00,0x60,0x60,0x00,0x00},	// .
		{0x20,0x10,0x08,0x04,0x02},	// /
 
		{0x3E,0x51,0x49,0x45,0x3E},	// 0
		{0x00,0x42,0x7F,0x40,0x00},	// 1
		{0x42,0x61,0x51,0x49,0x46},	// 2
		{0x21,0x41,0x45,0x4B,0x31},	// 3
		{0x18,0x14,0x12,0x7F,0x10},	// 4
		{0x27,0x45,0x45,0x45,0x39},	// 5
		{0x3C,0x4A,0x49,0x49,0x30},	// 6
		{0x01,0x71,0x09,0x05,0x03},	// 7
		{0x36,0x49,0x49,0x49,0x36},	// 8
		{0x06,0x49,0x49,0x29,0x1E},	// 9
 
		{0x36,0x36,0x00,0x00,0x00},	// :
		{0x56,0x36,0x00,0x00,0x00},	// ;
		{0x08,0x14,0x22,0x41,0x00},	// <
		{0x14,0x14,0x14,0x14,0x14},	// =
		{0x00,0x41,0x22,0x14,0x08},	// >
		{0x02,0x01,0x51,0x09,0x06},	// ?
		{0x30,0x49,0x79,0x41,0x3E},	// @
 
		{0x7E,0x11,0x11,0x11,0x7E},	// A
		{0x7F,0x49,0x49,0x49,0x36},	// B
		{0x3E,0x41,0x41,0x41,0x22},	// C
		{0x7F,0x41,0x41,0x22,0x1C},	// D
		{0x7F,0x49,0x49,0x49,0x41},	// E
		{0x7F,0x09,0x09,0x09,0x01},	// F
		{0x3E,0x41,0x49,0x49,0x7A},	// G
		{0x7F,0x08,0x08,0x08,0x7F},	// H
		{0x00,0x41,0x7F,0x41,0x00},	// I
		{0x20,0x40,0x41,0x3F,0x01},	// J
		{0x7F,0x08,0x14,0x22,0x41},	// K
		{0x7F,0x40,0x40,0x40,0x40},	// L
		{0x7F,0x02,0x0C,0x02,0x7F},	// M
		{0x7F,0x04,0x08,0x10,0x7F},	// N
		{0x3E,0x41,0x41,0x41,0x3E},	// O
		{0x7F,0x09,0x09,0x09,0x06},	// P
		{0x3E,0x41,0x51,0x21,0x5E},	// Q
		{0x7F,0x09,0x19,0x29,0x46},	// R
		{0x46,0x49,0x49,0x49,0x31},	// S
		{0x01,0x01,0x7F,0x01,0x01},	// T
		{0x3F,0x40,0x40,0x40,0x3F},	// U
		{0x1F,0x20,0x40,0x20,0x1F},	// V
		{0x3F,0x40,0x30,0x40,0x3F},	// W
		{0x63,0x14,0x08,0x14,0x63},	// X
		{0x07,0x08,0x70,0x08,0x07},	// Y
		{0x61,0x51,0x49,0x45,0x43},	// Z
 
		{0x00,0x7F,0x41,0x41,0x00},	// [
		{0x02,0x04,0x08,0x10,0x20},	// backslash
		{0x00,0x41,0x41,0x7F,0x00},	// ]
		{0x04,0x02,0x01,0x02,0x04},	// ^
		{0x40,0x40,0x40,0x40,0x40},	// _
		{0x00,0x01,0x02,0x04,0x00},	// `
 
		{0x20,0x54,0x54,0x54,0x78},	// a
		{0x7F,0x50,0x48,0x48,0x30},	// b
		{0x38,0x44,0x44,0x44,0x20},	// c
		{0x38,0x44,0x44,0x48,0x7F},	// d
		{0x38,0x54,0x54,0x54,0x18},	// e
		{0x08,0x7E,0x09,0x01,0x02},	// f
		{0x0C,0x52,0x52,0x52,0x3E},	// g
		{0x7F,0x08,0x04,0x04,0x78},	// h
		{0x00,0x44,0x7D,0x40,0x00},	// i
		{0x20,0x40,0x44,0x3D,0x00},	// j
		{0x7F,0x10,0x28,0x44,0x00},	// k
		{0x00,0x41,0x7F,0x40,0x00},	// l
		{0x78,0x04,0x58,0x44,0x78},	// m
		{0x7C,0x08,0x04,0x04,0x78},	// n
		{0x38,0x44,0x44,0x44,0x38},	// o
		{0x7C,0x14,0x14,0x14,0x08},	// p
		{0x08,0x14,0x14,0x18,0x7C},	// q
		{0x7C,0x08,0x04,0x04,0x08},	// r
		{0x48,0x54,0x54,0x54,0x20},	// s
		{0x04,0x3F,0x44,0x40,0x20},	// t
		{0x3C,0x40,0x40,0x20,0x7C},	// u
		{0x1C,0x20,0x40,0x20,0x1C},	// v
		{0x3C,0x40,0x30,0x40,0x3C},	// w
		{0x44,0x28,0x10,0x28,0x44},	// x
		{0x0C,0x50,0x50,0x50,0x3C},	// y
		{0x44,0x64,0x54,0x4C,0x44},	// z
 
		{0x00,0x08,0x36,0x41,0x00},	// {
		{0x00,0x00,0x7F,0x00,0x00},	// |
		{0x00,0x41,0x36,0x08,0x00},	// }
		{0x0C,0x02,0x0C,0x10,0x0C},	// ~
 
		{0x00,0x00,0x00,0x00,0x00}
};




int main(void) { 
	//////////////////////
	/// Initialization ///
	//////////////////////
	DDRB |= 255; //Set PORTB for Output (using bit-OR statement)
	DDRD |= 255; //Set PORTD for Output (using bit-OR statement)

	//Configure Timer Mode: CTC
	TCCR1B |= (1 << WGM12);

	//Enable CTC Interrupt
	TIMSK |= (1 << OCIE1A);
	
	//Enable global Interrupt
	sei();

	//Set Compare Value for 1Hz
	OCR1A = 50000; //Set compare value to 1Hz at 1mHz clock fOSC/64

	//Timer control register
	//TCCR1B |= ((1 << CS00) | (1 << CS01)); // Set up timer for fOSC/64 prescaler
	TCCR1B |= (1 << CS00); //Set up timer for no prescaler
	int i;
	for (i = 0; i < 30; i++)
		data[i] = 3 * i;


	////////////
	/// Loop ///
	////////////
	for (;;) { //Infinite Loop
				

	}
}

//Interrupt Service Routine
ISR(TIMER1_COMPA_vect) {
	int i = 0;
	int foo;

	foo = 0;
	for (i = 0; i < 8; i++)
		foo |= (((data[i] >> index) & 0x01) << i );

	softwareShiftOut(foo);

	index++;
	if (index > 8)
		index = 0;
}


//Software Shift Out
//Untested
void softwareShiftOut(uint8_t output) {
	int i;
	//latch low
	PORTB &= ~(1 << LATCH_PIN_PORTB);
	//Data Low
	PORTB &= ~(1 << DATA_PIN_PORTB);
	//Loop 0-7
	for (i = 0; i < 7; i++)
	{	
		//Clock Low
		PORTB &= ~(1 << CLOCK_PIN_PORTB);
		//Data on/off
		if (((output >> i) & 0x01) == 1)
			PORTB |= (1 << DATA_PIN_PORTB);
		else
			PORTB &= ~(1 << DATA_PIN_PORTB);
		//Clock On
		PORTB |= (1 << CLOCK_PIN_PORTB);
		//Data off
		PORTB &= ~(1 << DATA_PIN_PORTB);
	}
	//Clock off
	PORTB &= ~(1 << CLOCK_PIN_PORTB);
	//Latch high
	PORTB |= (1 << LATCH_PIN_PORTB);
}








